#+ -*- coding: utf-8 -*-
import os
from typing import List

import aiofiles
from loguru import logger
from pydantic import BaseModel
from fastapi import Request, UploadFile, File, Form, BackgroundTasks

from schemas.response_entity import JsonModel
from configs import UPLOAD_AUDIO_FILE_DIR
from utils.hash_utils import cal_md5
from utils.file_utils import normalize_filename_extension, to_rel_path
from db.repository.audio_file import (
    db_create_audio_file,
    db_list_audio_files,
    db_list_audio_files_by_user_groups,
    db_get_audio_by_id,
    db_update_audio_file_delete_state,
    db_update_audio_file,
    db_get_audio_by_hash_name,
)
from db.repository.user import db_get_user_group_ids
from .utils import parse_audio_background


# 上传音频文件
# 功能：管理员上传音频（mp3/wav），去重保存并触发后台解析
async def upload_audio(
    request: Request,
    background: BackgroundTasks,
    token=Form(...),
    file: UploadFile = File(...),
    file_name: str = Form(...),
    group_ids: List[int] = Form(None),
    company_name: str = Form(...),
    group_name: str = Form(...),
    keywords: List[str] = Form(None),
    comment: str = Form(None),
):
    user = request.state.user
    if not user.check_admin_role():
        return JsonModel(code=401, data=None, msg=f"用户无权限").to_response()

    # allowed_extensions = {"mp3", "wav", "m4a", "flac", "aac", "ogg"}
    allowed_extensions = {"wav"}
    normalized_filename = normalize_filename_extension(file_name)
    if "." in normalized_filename:
        file_suffix = normalized_filename.rsplit(".", 1)[-1]
    else:
        file_suffix = ""

    if file_suffix not in allowed_extensions:
        return JsonModel(code=400, data=None, msg=f"不支持的文件类型: {file_suffix}，仅支持 {', '.join(allowed_extensions)}").to_response()

    try:
        file_content = await file.read()
        file_md5 = cal_md5(file_content)
        file_size = len(file_content)

        # 计算基于内容的唯一哈希文件名，并检查是否已存在记录（去重）
        file_hash_name = f"{file_md5}.{file_suffix}"
        existed = db_get_audio_by_hash_name(file_hash_name)
        if existed and not getattr(existed, "is_delete", False):
            return JsonModel(code=200, data={"id": str(existed.id), "duplicated": True}, msg=f"音频已存在:{normalized_filename}").to_response()

        # 磁盘目录准备
        dir_path = os.path.join(UPLOAD_AUDIO_FILE_DIR, file_md5)
        if not os.path.exists(dir_path):
            os.makedirs(dir_path)
        file_hash_path = os.path.join(dir_path, file_hash_name)

        # 若磁盘已有相同内容文件，直接复用；否则写入
        if not os.path.exists(file_hash_path):
            async with aiofiles.open(file_hash_path, "wb") as f:
                await f.write(file_content)
            logger.info(f"音频保存成功: {file_hash_path}")

        parsed_group_ids = group_ids or []
        parsed_keywords = keywords or []

        audio = db_create_audio_file(
            user_id=user.id,
            hash_name=file_hash_name,
            name=normalized_filename,
            location=to_rel_path(file_hash_path),
            file_type=file_suffix,
            file_size=file_size,
            status="uploaded",
            company_name=company_name,
            group_name=group_name,
            keywords=parsed_keywords,
            comment=comment,
            group_ids=parsed_group_ids,
        )
        background.add_task(parse_audio_background, audio, file_hash_path)
        logger.info(f"Scheduled background parsing for {normalized_filename} at {file_hash_path}")
        return JsonModel(code=200, data={"id": str(audio.id)}, msg=f"上传音频:{normalized_filename}成功").to_response()
    except Exception as e:
        logger.error(e)
        return JsonModel(code=500, data=None, msg="上传失败").to_response()


# 查询音频列表
# 功能：超级管理员查看全部，其余按用户组过滤
async def list_audio(request: Request, page: int = 1, page_size: int = 50, name: str = ""):
    user = request.state.user
    try:
        offset = (page - 1) * page_size
        if user.check_superman_role():
            items, total = db_list_audio_files(name_like=name or None, offset=offset, limit=page_size)
        else:
            # 非超级管理员只能查看该用户所在组的可查看文件
            user_group_ids = db_get_user_group_ids(user)
            items, total = db_list_audio_files_by_user_groups(user_group_ids, name_like=name or None, offset=offset, limit=page_size)
        
        return JsonModel(
            code=200, 
            data={
                "items": [i.to_json() for i in items],
                "total": total,
                "page": page,
                "page_size": page_size
            }, 
            msg="success"
        ).to_response()
    except Exception as e:
        logger.error(e)
        return JsonModel(code=500, data=None, msg="查询失败").to_response()


# 获取音频详情
# 功能：管理员按ID查询音频详情
async def get_audio(request: Request, audio_id: str):
    user = request.state.user
    if not user.check_admin_role():
        return JsonModel(code=401, data=None, msg=f"用户无权限").to_response()
    try:
        audio = db_get_audio_by_id(audio_id)
        if not audio or getattr(audio, "is_delete", False):
            return JsonModel(code=404, data=None, msg="音频不存在").to_response()
        return JsonModel(code=200, data=audio.to_json(), msg="success").to_response()
    except Exception as e:
        logger.error(e)
        return JsonModel(code=500, data=None, msg="查询失败").to_response()


# 删除音频（软删）
# 功能：管理员将音频标记为删除
async def delete_audio(request: Request, audio_id: str):
    user = request.state.user
    if not user.check_admin_role():
        return JsonModel(code=401, data=None, msg=f"用户无权限").to_response()
    try:
        ok = db_update_audio_file_delete_state(audio_id, True)
        if not ok:
            return JsonModel(code=404, data=None, msg="音频不存在").to_response()
        return JsonModel(code=200, data=None, msg="删除成功").to_response()
    except Exception as e:
        logger.error(e)
        return JsonModel(code=500, data=None, msg="删除失败").to_response()


class AudioUpdate(BaseModel):
    name: str | None = None
    location: str | None = None
    file_type: str | None = None
    file_size: float | None = None
    status: str | None = None
    company_name: str | None = None
    group_name: str | None = None
    content: str | None = None
    summary: str | None = None
    keywords: list[str] | None = None
    comment: str | None = None
    group_ids: list[int] | None = None


# 更新音频信息
# 功能：管理员更新音频基础信息、内容摘要、关键词与用户组等
async def update_audio(request: Request, audio_id: str, audio: AudioUpdate):
    user = request.state.user
    if not user.check_admin_role():
        return JsonModel(code=401, data=None, msg=f"用户无权限").to_response()
    if not any([
        audio.name,
        audio.location,
        audio.file_type,
        audio.file_size is not None,
        audio.status,
        audio.company_name,
        audio.group_name,
        audio.summary,
        audio.keywords is not None,
        audio.comment,
    ]):
        return JsonModel(code=300, data=None, msg="缺少更新内容").to_response()
    try:
        updated = db_update_audio_file(
            audio_id,
            name=audio.name,
            location=audio.location,
            file_type=audio.file_type,
            file_size=audio.file_size,
            status=audio.status,
            company_name=audio.company_name,
            group_name=audio.group_name,
            content=audio.content,
            summary=audio.summary,
            keywords=audio.keywords,
            comment=audio.comment,
            group_ids=audio.group_ids,
        )
        if not updated:
            return JsonModel(code=404, data=None, msg="音频不存在").to_response()
        return JsonModel(code=200, data=None, msg="更新成功").to_response()
    except Exception as e:
        logger.error(e)
        return JsonModel(code=500, data=None, msg="更新失败").to_response()


# 兼容方法：通过ID获取音频详情
# 功能：转发到 `get_audio`
async def get_audio_by_id(request: Request, audio_id: str):
    return await get_audio(request, audio_id)

